package com.tool.cn.util;

import java.io.File;
import java.math.BigDecimal;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.IntStream;

import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.sf.chineseutils.ChineseUtils;


/**
 * 字符串工具类
 * 
 * @author wangzh 2016年9月18日 上午9:12:04
 */
public final class StringUtil {
	
	private static final Logger log = LoggerFactory.getLogger(StringUtil.class);
	
	public static final String MD2 = "MD2";
	public static final String MD5 = "MD5";
	public static final String SHA_1 = "SHA1";
	public static final String SHA_256 = "SHA256";
	public static final String SHA_384 = "SHA384";
	public static final String SHA_512 = "SHA512";

	public static final String line="-";
	
	
    /**
     * 将str重复count次，返回结果
     *
     * @param str
     * @param count
     * @return
     */
    public static String getRepeatChar(String str, int count) {
        StringBuilder res = new StringBuilder();
        IntStream.range(0, count).forEach(i -> res.append(str));
        return res.toString();
    }
    
	/**
	 * 提取url域名
	 * @param url
	 * @return
	 */
	public static String getDomainName(String url) {
		try {
			return new URL(url).getHost();
		} catch (Exception e) {
			log.error(url+ " Get Host Error",e);
		}
		return "";
	}
	
	/**
	 * 调用scp命令时，ip格式转换
	 * @param ip
	 * @return
	 */
	public static String scpIp(String ip) {
		if(ip.contains(":")) {  //ipv6
			return "["+ip+"]";
		}
		return ip;
	}
    
    /**
     * 将str重复count次，返回结果
     *
     * @param str
     * @param count
     * @return
     */
    public static String getRepeatChar(char str, int count) {
        return getRepeatChar(String.valueOf(str), count);
    }
	
	/**
	 * 字符串转码
	 * 
	 * @param sourceStr
	 *            待转码字符串
	 * @param algorithmsName
	 *            算法名称(如:MD2,MD5,SHA1,SHA256,SHA384,SHA512)
	 * @return
	 */
	public static String passAlgorithmsCiphering(String sourceStr, String algorithmsName) {
		String password = "";
		switch (algorithmsName) {
		case MD2:
			password = DigestUtils.md2Hex(sourceStr);
			break;
		case MD5:
			password = DigestUtils.md5Hex(sourceStr);
			break;
		case SHA_1:
			password = DigestUtils.sha1Hex(sourceStr);
			break;
		case SHA_256:
			password = DigestUtils.sha256Hex(sourceStr);
			break;
		case SHA_384:
			password = DigestUtils.sha384Hex(sourceStr);
			break;
		case SHA_512:
			password = DigestUtils.sha512Hex(sourceStr);
			break;
		}
		return password;
	}

	/**
	 * 判断字符串是否为空
	 */
	public static boolean isEmpty(String str) {
		if (str == null || str.trim().isEmpty()) {
			return true;
		}
		return false;
	}
	
	/**
	* 字符串转换为Ascii
	* @param value
	* @return
	*/
	public static String stringToAscii(String value){
		StringBuffer sbu = new StringBuffer();
		char[] chars = value.toCharArray();
		for (int i = 0; i < chars.length; i++) {
			if(i != chars.length - 1)
			{
				sbu.append((int)chars[i]).append(",");
			}
			else {
				sbu.append((int)chars[i]);
			}
		}
		return sbu.toString();
	}
	
	/**
	* Ascii转换为字符串
	* @param value
	* @return
	*/
	public static String asciiToString(String value){
		StringBuffer sbu = new StringBuffer();
		String[] chars = value.split(",");
		for (int i = 0; i < chars.length; i++) {
			sbu.append((char) Integer.parseInt(chars[i]));
		}
		return sbu.toString();
	}

	/**
	 * 判断字符串是否不为空
	 */
	public static boolean isNotEmpty(String str) {
		return !isEmpty(str);
	}
	
	/**
	 * 判断文件夹分隔符是否为linux系统结尾，不是追加
	 * @param path
	 * @return
	 */
	public static String checkLinuxPath(String path) {
		if(!path.endsWith("/")) {
			path+="/";
		}
		return path;
	}
	
	/**
	 * 效验字符长度，小于14位补零，大于截取
	 * @param createTime
	 * @return
	 */
	public static String checkLengthStr(String createTime) {
		if(createTime.length()==14) {
			return createTime;
		}
		if(createTime.length()>14) {
			return createTime.substring(0, 14);
		}
		int size=14-createTime.length();
		StringBuilder bud=new StringBuilder(createTime);
		for(;size>0;size--) {
			bud.append("0");
		}
		return bud.toString();
	}

	/**
	 * 繁体转简体
	 */
	public static final String tradToSimp(String context) {
		return ChineseUtils.tradToSimp(context);
	}

	/**
	 * 判断是否为数字，正负数和 小数
	 */
	public static boolean isNumber(String context) {
		if(isEmpty(context)){
			return false;
		}
		String regx="-?[0-9]+";
		if(context.contains(".")){
			regx="-?[0-9]+.?[0-9]+";
		}
		Pattern pattern = Pattern.compile(regx);
		Matcher isNum = pattern.matcher(context);
		if (!isNum.matches()) {
			return false;
		}
		return true;
	}
	
	/**
	 * 字符串数字
	 * @param context
	 * @param defaultInt
	 * @return
	 */
	public static int strToInt(String context,int defaultInt) {
		if(isNumber(context)) {
			return Integer.parseInt(context);
		}
		return defaultInt;
	}

	/**
	 * 字符串反转
	 */
	public static String toReversal(String context) {
		return new StringBuffer(context).reverse().toString();
	}

	/**
	 * 高效分隔符实例
	 * 
	 * @param context
	 */
	public static List<String> model(String context) {
		StringTokenizer work = new StringTokenizer(context, ",");// 可设定第三个参数，第三个参数设定时，返回分隔符
		List<String> result=new ArrayList<String>();
		while (work.hasMoreTokens()) {
			String te = work.nextToken();
			result.add(te);
		}
		return result;
	}
	
	/**
	 * 去除字符串中\r\n\t
	 */
	public static String replaceBlank(String context) {
        String dest = "";
        if (context!=null) {
            Pattern p = Pattern.compile("\\s*|\t|\r|\n");
            Matcher m = p.matcher(context);
            dest = m.replaceAll("");
        }
        return dest;
    }

	/**
	 * 字符串提取单个int值
	 */
	public static Integer getInt(String context){
		return Integer.parseInt(getIntStr(context));
	}
	
	/**
	 * 字符串提取整数字符串
	 * @param context
	 * @return
	 */
	public static String getIntStr(String context){
		String regEx="[^0-9]";  
		Pattern p = Pattern.compile(regEx);  
		Matcher m = p.matcher(context);  
		context=m.replaceAll("").trim();
		if(isEmpty(context)){
			context="0";
		}
		return context;
	}
	
	/**
	 * 数字前补0到指定长度，数字自身超过指定长度，不操作
	 * @param size 数字最终长度
	 * @param num 数字
	 * @return
	 */
	public static String getNum(int size,int num) {
		String numString=String.valueOf(num);
		size=size-numString.length();
		if(size>0) {
			for(int i=0;i<size;i++) {
				numString="0"+numString;
			}
		}
		return numString;
	}
	
	/**
	 * 递归去除下滑线，并将下滑线后字母转大写
	 * @param name 带下划线字符串
	 * @param anotherName  下划线字符串
	 * @return
	 */
	public static String getName(String name,String  anotherName) {
		name=anotherName;
		String key=".";
		//如果最后一个是_ 不做转换
		if(name.indexOf(key)>0&&name.length()!=name.indexOf(key)+1){
			int lengthPlace=name.indexOf(key);
			name=name.replaceFirst("\\"+key, "");
			String s=name.substring(lengthPlace, lengthPlace+1);
			s=s.toUpperCase();
			anotherName=name.substring(0,lengthPlace)+s+name.substring(lengthPlace+1);
		}else{
			return  anotherName;
		}
		return getName(name,anotherName);
	}
	
	/**
	 * 正则匹配字符串中指定开头结尾的字符，未去重
	 * @param context
	 * @param start
	 * @param end
	 * @param add 是否添加开头和结尾 true添加  false 不添加
	 * @return
	 */
	public static List<String> gerReg(String context,String start,String end,boolean add){
		Pattern pt=Pattern.compile("((?<="+start+").*?(?="+end+"))+");  //去掉最后+，只匹配一个
		Matcher ma=pt.matcher(context);
		
		List<String> data=new ArrayList<String>();
		 while (ma.find()){
	            String res = ma.group();
	            if (res.length()>0){
	            	if(add) {
	            		data.add(start+res+end);
	            	}else {
	            		data.add(res);
	            	}
	                
	            }
	        }
		 
		return data;
	}
	/**
	 * 		String regex="(.{4})"+key+"(.{16})$";  //正数第四到，倒数16位之间
 boolean 	state=Pattern.matches(regex, startRowkey);
		System.out.println(regex+" "+state);
	 */

	 /**
	  * 获取文件编号 P01格式
	  * @param index
	  * @return
	  */
	 public static String getFileIndex(int index) {
		 if(index>0) {
			 if(index<10) {
				 return "P0"+index;
			 }else if(index<20) {
				 return "P"+index;
			 }
		 }
		 return "P01";
	 }
	 
	 /**
	  * 去除数据尾部.0多余字符
	  * @param value
	  * @return
	  */
	 public static String checkValue(String value) {
			if(isNumber(value)&& value.contains(".")) {  //去除无效0
				String[] dataTmp=value.split("\\.");
				if(dataTmp[1].equals("0")) {
					value=dataTmp[0];
				}else {
					value=value.replaceAll("0*$","");
				}
				
				if(value.endsWith(".")) {
					value=value.substring(0, value.length()-1);
				}
			}
			return value;
	 }
	 
	 /**
	  * 正则效验
	  * @param reg 正则
	  * @param param 字符串
	  * @return
	  */
	 public static boolean checkStr(String reg,String param) {
		 return Pattern.matches(reg, param);
	 }
	 
	 /**
	  * 正则验证开头和结尾固定，中间数字和大小写字母
	  * @param start
	  * @param end
	  * @return
	  */
	 public static boolean checkStr(String start,String end,String param) {
		 String reg="^"+start+"[_0-9a-zA-Z]*"+end+"$";
		 return checkStr(reg, param);
	 }
	 
		/**
		 * 是否为科学计数法数字
		 * @return
		 */
		public static boolean isErrorNumber(String value) {
			String regx = "^((-?\\d+.?\\d*)[Ee]{1}(-?\\d+))$";//科学计数法正则表达式
		    Pattern pattern = Pattern.compile(regx);
	        return pattern.matcher(value).matches();
		}
		
		/**
		 * 科学计数法转正常数据
		 * @param value
		 * @return
		 */
		public static String doubleNumber(String value) {
			BigDecimal bd = new BigDecimal(value);
			return bd.toPlainString();
		}
		
		/**
		 * 替换字符串网页多余js、style、html、&nbsp;等特殊字符
		 * @param context
		 * @return
		 */
		public static String formatString(String context) {
			// 定义script的正则表达式{或<script[^>]*?>[\\s\\S]*?<\\/script>
//			String regEx_script = "<[\\s]*?script[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?script[\\s]*?>";
			// 定义style的正则表达式{或<style[^>]*?>[\\s\\S]*?<\\/style>
//			String regEx_style = "<[\\s]*?style[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?style[\\s]*?>";
			// 定义HTML标签的正则表达式
			String regEx_html = "<[^>]+>";
			// 定义一些特殊字符的正则表达式 如：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
			String regEx_special = "\\&[a-zA-Z]{1,10};";
			Pattern p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);
			Matcher m_html = p_html.matcher(context);
			context = m_html.replaceAll("");

			p_html = Pattern.compile(regEx_special, Pattern.CASE_INSENSITIVE);
			m_html = p_html.matcher(context);
			context = m_html.replaceAll("");
			return context;
		}
		
		/**
	     * 版本一是否大于版本二
	     *
	     * @param version1 版本一
	     * @param version2 版本二
	     * @return int 大于时：大于等于 1，小于返回小于等于 -1，相等返回0
	     */
	    public static int compareAppVersion(String version1, String version2) {
	        if (version1 == null || version2 == null) {
	            throw new RuntimeException("版本号不能为空");
	        }
	        // 注意此处为正则匹配，不能用.
	        String[] versionArray1 = version1.split("\\.");
	        String[] versionArray2 = version2.split("\\.");
	        int idx = 0;
	        // 取数组最小长度值
	        int minLength = Math.min(versionArray1.length, versionArray2.length);
	        int diff = 0;
	        // 先比较长度，再比较大小
	        while (idx < minLength&& (diff = versionArray1[idx].length() - versionArray2[idx].length()) == 0&& (diff = versionArray1[idx].compareTo(versionArray2[idx])) == 0) {
	        	++idx;
	        }

	        // 如果已经分出大小，则直接返回，如果未分出大小，则再比较位数，有子版本的为大
	        diff = (diff != 0) ? diff : versionArray1.length - versionArray2.length;
	        return diff;
	    }
	    
		/**
		 * 路径后增加目录分隔符
		 * @param path
		 * @return
		 */
		public static String checkPath(String path) {
			if(!path.endsWith(File.separator)) {
				path+=File.separator;
			}
			return path;
		}
		
		/**
		 * window文件夹分隔符改linux
		 * @param path
		 * @return
		 */
		public static String pathWinToLinxe(String path) {
			if(path.contains("\\")) {
				path=path.replace("\\", "/");
			}
			return path;
		}
		
		/**
		 * 数组、list、set、map转字符串
		 * @param object
		 * @return
		 */
		public static String objToString(Object object) {
			
			if(object.getClass().isArray()) {  //数组
				return arrayToString((Object[])object);
				
			}else if (object instanceof Collection< ? >){  //集合
				return CollectionToString((Collection<?> )object);
			}else if (object instanceof Map<?,?>){  //map
				return mapToString((Map<?,?>)object);
			}else if(object instanceof String){
				return String.valueOf(object);
			}else {
				return "";
			}
		}
		
		/**
		 * 数组转字符串
		 * @param <T>
		 * @param dataList 数组数据
		 * @return
		 */
		public static  String arrayToString(Object[] dataList) {
			return arrayToString(dataList,",");
		}
		
		/**
		 * 数组转字符串
		 * @param dataList 数组数据 
		 * @param separate 分隔符
		 * @return
		 */
		public static  String arrayToString(Object[] dataList,String separate) {
			StringBuilder bud=new StringBuilder();
			
			int i=0;
			for(Object data:dataList) {
				if(i!=0) {
					bud.append(separate);
				}
				bud.append(data);
				i++;
			}
			return bud.toString();
		}
		
		/**
		 * list转字符串
		 * @param <T>
		 * @param dataList 集合数据
		 * @return
		 */
		public static <T> String listToString(List<T> dataList) {
			return CollectionToString(dataList,",");
		}
		
		/**
		 * list转字符串
		 * @param <T>
		 * @param dataList 集合数据 
		 * @param separate 分隔符
		 * @return
		 */
		public static <T> String listToString(List<T> dataList,String separate) {
			return CollectionToString(dataList,separate);
		}
		
		/**
		 * Set转字符串
		 * @param <T>
		 * @param dataList 集合数据
		 * @return
		 */
		public static <T> String setToString(Set<T> dataList) {
			return CollectionToString(dataList,",");
		}
		
		/**
		 * Set转字符串
		 * @param <T>
		 * @param dataList 集合数据 
		 * @param separate 分隔符
		 * @return
		 */
		public static <T> String setToString(Set<T> dataList,String separate) {
			return CollectionToString(dataList,separate);
		}
		
		/**
		 * collection 集合转字符串
		 * @param <T>
		 * @param dataList
		 * @param separate
		 * @return
		 */
		public static <T> String CollectionToString(Collection<T> dataList) {
			return CollectionToString(dataList,",");
		}
		
		/**
		 * collection 集合转字符串
		 * @param <T>
		 * @param dataList
		 * @param separate
		 * @return
		 */
		public static <T> String CollectionToString(Collection<T> dataList,String separate) {
			StringBuilder bud=new StringBuilder();
			
			int i=0;
			for(T data:dataList) {
				if(i!=0) {
					bud.append(separate);
				}
				bud.append(data);
				i++;
			}
			return bud.toString();
		}
		
		/**
		 * replace 最后一个字符串
		 * @param data 数据
		 * @param oldStr 旧字符
		 * @param newStr 新字符
		 * @return
		 */
		public static String replaceLast(String data, String oldStr, String newStr) {
			return data.replaceFirst("(?s)"+oldStr+"(?!.*?"+oldStr+")", newStr);
		}
		
		/**
		 * map转string
		 * @param relation
		 * @return
		 */
		public static String mapToString(Map<?, ?> dataMap) {
			StringBuilder bud=new StringBuilder();
			bud.append("[");
			int i=0;
			for(Entry<?, ?>one:dataMap.entrySet()) {
				if(i>0) {
					bud.append(",");
				}
				bud.append(one.getKey()).append(":").append(one.getValue());
				i++;
			}
			bud.append("]");
			return bud.toString();
		}
		
		/**
		 * 格式化字符串
		 * @param data 原字符串数据
		 * @param param 替换数组
		 * @return
		 */
		public static String formatString(String data,Object... param) {
			if(param.length<=0||!data.contains("{}")) {
				return data;
			}
			String[] dataList=data.split("\\{\\}",-1 );
			int allSize=dataList.length;
			
			final StringBuilder builder = new StringBuilder();
			int i=0;
			int size=param.length;
			int add=0;
			for(int j=0;j<allSize;j++) {

				if(i<size) {
					builder.append(dataList[j]);
					builder.append(param[i]);
					i++;
					add=1;
				}else if(isNotEmpty(dataList[j])) {

					//如果上一个内容为无替换添加，则增加分隔符
					if(add==0) {
						builder.append("{}");
					}
					builder.append(dataList[j]);

					add=0;
				}else{
					builder.append("{}");
				}
			}
			return builder.toString();
		}
		
}
